package jsr292.java.util;

import java.util.Arrays;
import java.util.Comparator;

public final class Objects {
    private Objects() {
        // do nothing
    }

    public static boolean equals(Object a, Object b) {
        return a == b || (a != null && a.equals(b));
    }

    public static boolean deepEquals(Object a, Object b) {
        if (a == b) {
            return true;
        }
        if (a == null || b == null) {
            return false;
        }
        Class<? extends Object> clazz = a.getClass();
        if (clazz.isArray() && clazz == b.getClass()) {
            if (clazz == boolean[].class) {
                return Arrays.equals((boolean[]) a, (boolean[]) b);
            }
            if (clazz == byte[].class) {
                return Arrays.equals((byte[]) a, (byte[]) b);
            }
            if (clazz == short[].class) {
                return Arrays.equals((short[]) a, (short[]) b);
            }
            if (clazz == char[].class) {
                return Arrays.equals((char[]) a, (char[]) b);
            }
            if (clazz == int[].class) {
                return Arrays.equals((int[]) a, (int[]) b);
            }
            if (clazz == long[].class) {
                return Arrays.equals((long[]) a, (long[]) b);
            }
            if (clazz == float[].class) {
                return Arrays.equals((float[]) a, (float[]) b);
            }
            if (clazz == double[].class) {
                return Arrays.equals((double[]) a, (double[]) b);
            }
            return Arrays.deepEquals((Object[]) a, (Object[]) b);
        }
        return a.equals(b);
    }

    public static int hashCode(Object o) {
        return o != null ? o.hashCode() : 0;
    }

    public static int hash(Object... values) {
        return Arrays.hashCode(values);
    }

    
    public static String toString(Object o) {
        return toString(o, "null");
    }

    public static String toString(Object o, String nullDefault) {
        return (o != null) ? o.toString() : nullDefault;
    }

    public static <T> int compare(T a, T b, Comparator<? super T> c) {
        return (a == b) ? 0 :  c.compare(a, b);
    }

    public static <T> T requireNonNull(T obj) {
        obj.getClass();
        return obj;
    }

    public static <T> T requireNonNull(T obj, String message) {
        if (obj == null)
            throw new NullPointerException(message);
        return obj;
    }
}
